package com.ctg.behavior.calc.impala.builder.ltv;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.ctg.behavior.calc.impala.report.ltv.CtLTVMeasureReport;
import com.ctg.behavior.calc.impala.report.ltv.CtLTVReport;
import com.ctg.behavior.calc.utils.CtCalcPropertyUtils;
import com.ctg.behavior.calc.utils.CtCalcUtils;
import com.ctg.behavior.common.calc.CtCalcPropertyType;
import com.ctg.behavior.common.consts.CtFieldConsts;
import com.ctg.behavior.common.ltv.CtLTVCalcData;
import com.ctg.behavior.common.ltv.CtLTVCell;
import com.ctg.behavior.common.ltv.CtLTVSubRow;
import com.ctg.behavior.utils.CtDateUtils;
import com.ctg.behavior.utils.CtDoubleUtils;

@Component
public class CtLTVCalcResultBuilder {

	@Autowired
	private CtLTVRowKeyBuilder rowkeyBuilder;

	// KEY: byValues数组中的元素，使用@符号分隔连接起来
	private static ThreadLocal<Map<String, CtLTVSubRow>> tlIndexGroupByRows = new ThreadLocal<>();
	// KEY: byValues数组中的元素，使用@符号分隔连接起来。若byFields为空(无分组),则为：$ALL
	private static ThreadLocal<Map<String, CtLTVSubRow>> tlIndexTotalRows = new ThreadLocal<>();
	// KEY: byValues数组中的元素，使用@符号分隔连接起来。若byFields为空(无分组),则为：$ALL
	private static ThreadLocal<Map<String, CtLTVSubRow>> tlIndexTotalDayRows = new ThreadLocal<>();
	// KEY: byValues数组中的元素，使用@符号分隔连接起来。若byFields为空(无分组),则为：$ALL
	private static ThreadLocal<Map<String, CtLTVSubRow>> tlIndexMeasureRows = new ThreadLocal<>();
	// KEY: byValues数组中的元素，使用@符号分隔连接起来。若byFields为空(无分组),则为：$ALL
	private static ThreadLocal<Map<String, CtLTVSubRow>> tlIndexDayRows = new ThreadLocal<>();

	public void resetResultBuilderTheadLocal() {
		Map<String, CtLTVSubRow> indexedRows = new HashMap<>();
		tlIndexGroupByRows.set(indexedRows);
		indexedRows = new HashMap<>();
		tlIndexTotalRows.set(indexedRows);
		indexedRows = new HashMap<>();
		tlIndexTotalDayRows.set(indexedRows);
		indexedRows = new HashMap<>();
		tlIndexMeasureRows.set(indexedRows);
		indexedRows = new HashMap<>();
		tlIndexDayRows.set(indexedRows);
	}

	public CtLTVCalcData doBuilder(CtLTVCalcData calcData, List<LinkedHashMap<String, Object>> calcResult, CtLTVReport report) {

		if(report.getMeasureReports().isEmpty()) {
			return calcData;
		}
		CtLTVMeasureReport measureReport = report.getMeasureReports().get(0);
		
		// 1. 通用字段
		calcData.setAppId(measureReport.getAppId());
		calcData.setBookmarkId(measureReport.getBookmarkId());
		calcData.setRequestId(measureReport.getRequestId());
		calcData.setReportUpdateTime(CtDateUtils.dateToString(new Date()));
		calcData.setDataUpdateTime(calcData.getDataUpdateTime());
		// 2. ByFields
		calcData.setByFields(measureReport.getByFields());

		List<CtCalcPropertyType> byPropertis = new ArrayList<>();
		{
			List<String> byFields = measureReport.getByFields();
			for (String oneField : byFields) {
				CtCalcPropertyType ptype = CtCalcPropertyUtils.getValueType(oneField);
				byPropertis.add(ptype);
			}
		}

		// 对查询结果分类
		this.buildThreadLocalRows(calcResult, byPropertis, report.getIsMultiMeasure());

		// 把ThreadLocal中的ROW填充到CtLTVCalcData
		List<CtLTVSubRow> calcDataRows = new ArrayList<>();
		if(!tlIndexGroupByRows.get().isEmpty()) {
			calcDataRows.addAll(tlIndexGroupByRows.get().values());
		} else {
			calcDataRows.addAll(tlIndexTotalRows.get().values());
			calcDataRows.addAll(tlIndexMeasureRows.get().values());
		}
		calcData.setRows(calcDataRows);

		return calcData;
	}

	public void buildThreadLocalRows(List<LinkedHashMap<String, Object>> calcResult, List<CtCalcPropertyType> byPropertis, Boolean isMultiMeasure) {

		// 3. 对查询结果分类
		for (LinkedHashMap<String, Object> oneResult : calcResult) {
			// 3.1 分组对应的ROW
			String groupByKey = rowkeyBuilder.buildGroupByKey(byPropertis, oneResult);
			CtLTVSubRow groupByRow = null;
			// 当存在分组时
			if (!StringUtils.isEmpty(groupByKey)) {
				groupByRow = tlIndexGroupByRows.get().get(groupByKey);
				if (null == groupByRow) {
					groupByRow = new CtLTVSubRow();
					String rowByValue = CtCalcUtils.buildLTVGroupByValues(oneResult, byPropertis);
					groupByRow.setByValue(rowByValue);
					tlIndexGroupByRows.get().put(groupByKey, groupByRow);
				}
			}
			// 3.2 总营收：当营收事件数量大于1时, 有"总营收"ROW
			CtLTVSubRow totalRow = null;
			if(isMultiMeasure){
				String totalKey = rowkeyBuilder.buildMeasureTotalKey(groupByKey, oneResult);
				totalRow = tlIndexTotalRows.get().get(totalKey);
				if (null == totalRow) {
					totalRow = new CtLTVSubRow();
					totalRow.setByValue(CtFieldConsts.FIELD_KEY_ALL);
					tlIndexTotalRows.get().put(totalKey, totalRow);
					// 若外层存在分组ROWS，则加入分组ROW的SubRows中
					if (null != groupByRow) {
						groupByRow.getSubRows().add(totalRow);
					}
				}
			}
			// 3.3 总营收 - 计算日(whichDay)对应的ROW
			CtLTVSubRow totalDayRow = null;
			if(isMultiMeasure){
				String totalDayKey = rowkeyBuilder.buildMeasureTotalDayKey(groupByKey, oneResult);
				totalDayRow = tlIndexTotalDayRows.get().get(totalDayKey);
				if (null == totalDayRow) {
					totalDayRow = new CtLTVSubRow();
					totalDayRow.setByValue(oneResult.get(CtFieldConsts.FIELD_KEY_CALC_DATE).toString());
					tlIndexTotalDayRows.get().put(totalDayKey, totalDayRow);
					// 加入总营收的TotalRow的子ROWS中
					totalRow.getSubRows().add(totalDayRow);
				}
			}
			// 3.4 统计事件对应的ROW
			String measureKey = rowkeyBuilder.buildMeasureKey(groupByKey, oneResult);
			CtLTVSubRow measureRow = tlIndexMeasureRows.get().get(measureKey);
			if (null == measureRow) {
				measureRow = new CtLTVSubRow();
				tlIndexMeasureRows.get().put(measureKey, measureRow);
				// 若外层存在分组ROWS，则加入分组ROW的SubRows中
				if (null != groupByRow) {
					groupByRow.getSubRows().add(measureRow);
				}
			}
			// 3.5 统计事件ROW - 计算日(whichDay)对应的ROW
			String calcDayKey = rowkeyBuilder.buildCalcDayKey(measureKey, oneResult);
			CtLTVSubRow calcDayRow = tlIndexDayRows.get().get(calcDayKey);
			if (null == calcDayRow) {
				calcDayRow = new CtLTVSubRow();
				calcDayRow.setByValue(oneResult.get(CtFieldConsts.FIELD_KEY_CALC_DATE).toString());
				tlIndexDayRows.get().put(calcDayKey, calcDayRow);
				// 加入统计事件ROW的SubRows中
				measureRow.getSubRows().add(calcDayRow);
			}
			// 3.6 根据oneResult中ltv的index来填充与计划Cell
			Integer ltvIndex = Integer.valueOf(oneResult.get("ltv").toString());
			String total = oneResult.get("total").toString();
			if (ltvIndex < 0) {
				/*********************************************
				 * 处理的是：初始人数 列
				 */
				// 本计算日的初始人数
				calcDayRow.setTotalPeople(Long.valueOf(total));
				// 累加到measureRow
				measureRow.setTotalPeople(measureRow.getTotalPeople() + Long.valueOf(total));
				// 填充到"总营收"totalDayRow(只需要首交填充该ROW的初始人数)
				if(null != totalDayRow && totalDayRow.getTotalPeople()<=0) {
					totalDayRow.setTotalPeople(Long.valueOf(total));
					// 累加到totalRow
					totalRow.setTotalPeople(totalRow.getTotalPeople() + Long.valueOf(total));
				}
			} else {
				/*********************************************
				 * 处理的是：LTVN 列
				 */
				// 填充calcDayRow中对应Cell
				{
					// 填充cell数组中下标小于ltvIndex的元素
					List<CtLTVCell> ltvCells = calcDayRow.getCells();
					for (int cindex = ltvCells.size(); cindex <= ltvIndex; cindex++) {
						CtLTVCell ltvCell = new CtLTVCell();
						ltvCells.add(ltvCell);
					}
					ltvCells.get(ltvIndex).setAmount(total);
				}
				// 累加measureRow中对应Cell
				{
					List<CtLTVCell> ltvCells = measureRow.getCells();
					for (int cindex = ltvCells.size(); cindex <= ltvIndex; cindex++) {
						CtLTVCell ltvCell = new CtLTVCell();
						ltvCells.add(ltvCell);
					}
					Double sumTotal = CtDoubleUtils.sum2Scale(ltvCells.get(ltvIndex).getAmount(), total);
					ltvCells.get(ltvIndex).setAmount(sumTotal.toString());
				}
				// 填充到"总营收"totalDayRow (不是首次，需要累加)
				if(null != totalDayRow) {
					// 填充cell数组中下标小于ltvIndex的元素
					List<CtLTVCell> ltvCells = totalDayRow.getCells();
					for (int cindex = ltvCells.size(); cindex <= ltvIndex; cindex++) {
						CtLTVCell ltvCell = new CtLTVCell();
						ltvCells.add(ltvCell);
					}
					ltvCells.get(ltvIndex).setAmount(total);
				}
				// 累加totalRow中对应Cell
				if(null != totalRow) {
					// 填充cell数组中下标小于ltvIndex的元素
					List<CtLTVCell> ltvCells = totalRow.getCells();
					for (int cindex = ltvCells.size(); cindex <= ltvIndex; cindex++) {
						CtLTVCell ltvCell = new CtLTVCell();
						ltvCells.add(ltvCell);
					}
					Double sumTotal = CtDoubleUtils.sum2Scale(ltvCells.get(ltvIndex).getAmount(), total);
					ltvCells.get(ltvIndex).setAmount(sumTotal.toString());
				}
				// TEMP 百分比暂不计算
//				// 计算百分比 - calcDayRow对应Cell的百分比
//				{
//					CtLTVCell dayLTVCell = calcDayRow.getCells().get(ltvIndex);
//					if(isMultiMeasure) {
//						CtLTVCell totalDayLTVCell = totalDayRow.getCells().get(ltvIndex);
//						Double percent = CtDoubleUtils.percent2Scale(dayLTVCell.getAmount(), totalDayLTVCell.getAmount());
//						dayLTVCell.setPercent(percent.toString());
//					} else {
//						dayLTVCell.setPercent("100.00");
//					}
//				}
//				// 计算百分比 - measureRow对应Cell的百分比
//				{
//					CtLTVCell measureLTVCell = measureRow.getCells().get(ltvIndex);
//					if(isMultiMeasure) {
//						CtLTVCell totalLTVCell = totalRow.getCells().get(ltvIndex);
//						Double percent = CtDoubleUtils.percent2Scale(measureLTVCell.getAmount(), totalLTVCell.getAmount());
//						measureLTVCell.setPercent(percent.toString());
//					} else {
//						measureLTVCell.setPercent("100.00");
//					}
//				}
				// 当存在分组时，即：groupByRow不为空时, 此时：
				// 1.groupByRow的cells等于measureRow和cells
				// 2.totalPeople的total为多个measureRow的total累加
				if(null != groupByRow) {
					groupByRow.setCells(CtCalcUtils.copyLTVCells(measureRow.getCells()));
					groupByRow.setTotalPeople(groupByRow.getTotalPeople() + measureRow.getTotalPeople());
				}
			}
		}

	}

}
